package mweb

import (
	"fmt"
	"gitee.com/dennis-mxx/gcode-common/menv"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/sessions"
)

var store sessions.Store

type SessionFactory func(prefix string, keyPairs ...[]byte) SessionCtx

var sessionOptions map[string]func(ginOption *menv.Web) sessions.Store

func init() {
	sessionOptions = map[string]func(ginOption *menv.Web) sessions.Store{
		"cookie": func(ginOption *menv.Web) sessions.Store {
			return sessions.NewCookieStore([]byte(ginOption.SessionSecret))
		},
		"file": func(ginOption *menv.Web) sessions.Store {
			if ginOption.SessionFile == "" {
				panic("session is file ,sessionFile is necessary")
			}
			return sessions.NewFilesystemStore(ginOption.SessionFile, []byte(ginOption.SessionSecret))
		},
	}
}
func RegisterSessionOptions(optionsName string, fun func(ginOption *menv.Web) sessions.Store) {
	sessionOptions[optionsName] = fun
}

func InitSession(ginOption *menv.Web) {
	if ginOption.Session == "" {
		ginOption.Session = "cookie"
	}
	if ginOption.SessionId == "" {
		ginOption.SessionId = "sessionId"
	}
	if ginOption.SessionSecret == "" {
		ginOption.SessionSecret = "v0XqbECSxbhMVocsJLaYPGabE7236Agu"
	}
	if fun := sessionOptions[ginOption.Session]; fun != nil {
		store = fun(ginOption)
	} else {
		panic(fmt.Sprintf("init session store failure ,  unsupported session type [%s]", ginOption.Session))
	}

}

// SessionCtx
// Stx 此处是获取session 的前置句柄，如需要对session进行安全验证操作请在初始化完成后覆盖
type SessionCtx interface {
	GetSession() (*sessions.Session, error)
	Save()
}

type SessionCtxDefault struct {
	ctx       *gin.Context
	session   *sessions.Session
	sessionId string
}

func (domain *SessionCtxDefault) GetSession() (*sessions.Session, error) {
	ctx := domain.ctx
	if domain.session != nil {
		return domain.session, nil
	} else {
		s, err := store.Get(ctx.Request, domain.sessionId)
		domain.session = s
		return s, err
	}
}
func (domain *SessionCtxDefault) Save() {
	if domain.session != nil {
		err := domain.session.Save(domain.ctx.Request, domain.ctx.Writer)
		if err != nil {
			panic(err)
		}
	}
}
